package org.yx.service.smfr.create_product_serial;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.yx.exception.BizException;
import org.yx.models.SbasProdMat;
import org.yx.models.SmfrOrdDef;
import org.yx.models.SmfrOrdOpr;
import org.yx.models.SmfrPsnDtl;
import org.yx.models.SmfrPsnSts;
import org.yx.service.bas.create_rule_code.BasCreateRuleCodeService;
import org.yx.service.smfr.insert_product_serial_history.SmfrInsertProductSerialHistoryIn;
import org.yx.service.smfr.insert_product_serial_history.SmfrInsertProductSerialHistoryService;
import org.yx.utils.BaseService;
import org.yx.utils.FieldMap;
import org.yx.utils.ServiceBeanUtil;

import com.xiaoleilu.hutool.collection.CollUtil;
import com.xiaoleilu.hutool.util.NumberUtil;
import com.xiaoleilu.hutool.util.ObjectUtil;
import com.xiaoleilu.hutool.util.StrUtil;

/**
 * 创建生产产品序列号（条码号）
 *
 * @author zxw
 * @since 2018/04/22
 **/
public class SmfrCreateProductSerialService extends BaseService {
    private final static String PSN_CODE = "PSN_CODE";

    public SmfrCreateProductSerialOut createProductSerial(SmfrCreateProductSerialIn in) throws Exception {
        String psn = StrUtil.isBlank(in.getPsn()) ? BasCreateRuleCodeService.createRuleCode(PSN_CODE) : in.getPsn();
        if (StrUtil.isBlank(psn)) {
            throw new BizException("SYS-0004", new FieldMap("parameter", "psn"));
        }
        if (StrUtil.isBlank(in.getMo())) {
            throw new BizException("SYS-0004", new FieldMap("parameter", "mo"));
        }
        if (in.getQty() == null || in.getQty().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BizException("SYS-0005", new FieldMap("parameter", "qty"), new FieldMap("value", in.getQty()));
        }

        if (selectWithPk(SmfrPsnSts.class, in.getUserOrgCode(), psn) != null) {
            // psn已经存在，创建失败
            throw new BizException("SMFR-0007", "产品批号${psn}已经存在。", new FieldMap("psn", psn));
        }

        SmfrOrdDef ordDef = selectWithPk(SmfrOrdDef.class, in.getUserOrgCode(), in.getMo());
        if (ordDef == null || "D".equals(ordDef.getMoStatus())) {
            throw new BizException("SMFR-0004", "生产工单${mo}不存在或已被删除。", new FieldMap("mo", in.getMo()));
        }

        SbasProdMat prodMat = selectWithPk(SbasProdMat.class, ordDef.getOrgCode(), ordDef.getMatCode(), ordDef.getMatVer());
        if (prodMat == null || new Character('D').equals(prodMat.getMatStatus())) {
            throw new BizException("SBAS-0001", "产品${matCode}不存在或已经删除。", new FieldMap("matCode", ordDef.getMatCode()));
        }

        if (new Character('H').equals(prodMat.getMatStatus())) {
            throw new BizException("SQCM-0001", "产品${matCode}当前被品质隔离。", new FieldMap("matCode", ordDef.getMatCode()));
        }

        // 工单不是Open或Process状态时，不能创建条码号
        if (!CollUtil.newArrayList("O", "P").contains(ordDef.getMoStatus())) {
            throw new BizException("SMFR-0008", "当生产工单${mo}的状态是${moStatus}，此操作是无效的。", new FieldMap("mo", ordDef.getMo()), new FieldMap("moStatus",
                    ordDef.getMoStatus()));
        }

        SmfrOrdOpr firstOrdOper = selectWithPk(SmfrOrdOpr.class, ordDef.getOrgCode(), ordDef.getMo(),
                ordDef.getPathCode(), 1);
        if (firstOrdOper == null) {
            throw new BizException("SMFR-0009", "生产工单${mo}的工艺路线或工序不存在。", new FieldMap("mo", ordDef.getMo()));
        }

        SmfrPsnSts psnSts = new SmfrPsnSts();
        copyProperties(in, psnSts);
        psnSts.setOrgCode(in.getUserOrgCode());
        psnSts.setPsn(psn);
        if (StrUtil.isBlank(psnSts.getLot())) {
            psnSts.setLot(psnSts.getPsn());
        }
        psnSts.setPathCode(firstOrdOper.getPathCode());
        psnSts.setOper(firstOrdOper.getOper());
        psnSts.setOperSeq(firstOrdOper.getOperSeq());
        psnSts.setMatCode(ordDef.getMatCode());
        psnSts.setMatVer(ordDef.getMatVer());
        psnSts.setDtlSeq(1);
        psnSts.setEventCode(in.getEventCode());
        psnSts.setUnit(prodMat.getUnit());
        psnSts.setCurrentLoc(ordDef.getLineCode());
        psnSts.setPsnType(in.getPsnType());

        insert(psnSts);

        SmfrInsertProductSerialHistoryIn hisIn = new SmfrInsertProductSerialHistoryIn();
        hisIn.setPsnSts(psnSts);
        ServiceBeanUtil.getBean(SmfrInsertProductSerialHistoryService.class).insertProductSerialHistory(hisIn);

        BigDecimal inQty = ordDef.getInQty();
        if (in.getQty() != null) {
            inQty = NumberUtil.add(inQty, in.getQty());
        }

        // 父批次下绑定有多个子批次，子批次处理数据同父批次
        if (CollUtil.isNotEmpty(in.getChildPsnList())) {
            List<SmfrPsnSts> children = new ArrayList<SmfrPsnSts>();
            for (SmfrPsnSts childPsn : in.getChildPsnList()) {
                if (StrUtil.isBlank(childPsn.getPsn())) {
                    throw new BizException("SYS-0005", FieldMap.of("parameter", "childPsnList.psn"), FieldMap.of(
                            "value", childPsn.getPsn()));
                }

                if (selectWithPk(SmfrPsnSts.class, psnSts.getOrgCode(), childPsn.getPsn()) != null) {
                    throw new BizException("SMFR-0007", "条码号${psn}已经存在。", FieldMap.of("psn", childPsn.getPsn()));
                }

                SmfrPsnSts cpsn = ObjectUtil.clone(childPsn);
                copyProperties(psnSts, cpsn);
                cpsn.setPsnType("C");
                cpsn.setQty(childPsn.getQty());
                cpsn.setCarryId(psnSts.getPsn());
                children.add(cpsn);

                if (in.getQty() == null) {
                    inQty = NumberUtil.add(inQty, cpsn.getQty());
                }
            }

            insertBatch(children);

            hisIn.setPsnSts(null);
            hisIn.setPsnStsList(children);
            ServiceBeanUtil.getBean(SmfrInsertProductSerialHistoryService.class).insertProductSerialHistory(hisIn);
        }

        SmfrPsnDtl psnDtl = new SmfrPsnDtl();
        copyProperties(psnSts, psnDtl);
        psnDtl.setSeqNum(psnSts.getDtlSeq());

        insert(psnDtl);

        ordDef.setInQty(inQty);
        update(ordDef, "inQty");

        if (ordDef.getActualStartTime() == null) {
            ordDef.setActualStartTime(getCurrentTime());

            update(ordDef, "actualStartTime");
        }

        //如果工单不是进行中状态，改成进行中
        if (!"P".equals(ordDef.getMoStatus())) {
            ordDef.setMoStatus("P");

            update(ordDef, "moStatus");
        }

        SmfrCreateProductSerialOut out = new SmfrCreateProductSerialOut();
        out.setPsn(psn);

        return out;
    }
}